#!/usr/bin/env python2
# -*- coding: utf-8 -*-

import re
import time
import json
import datetime
import traceback

from datetime import timedelta

from Ump import utils
from Ump.common import log
from Ump.common.utils import inspect_func
from Ump.common import exception

from Ump.objs.db import models
from Ump.objs.db.models import Folder, Cluster, AccessPolicy
from Ump.objs.session_wrapper import enable_log_and_session
from Ump.objs.manager_base import Manager

from Ump.umptypes import UmpPath
from agentapi import folder as folder_api

from Ump.objs.session_wrapper import _sw

from Ump.lich.volume import LichVolume, LichVolumeParam

LOG = log.get_log('Ump.objs.folder.manager')


class FolderManager(Manager):
    def __init__(self):
        super(FolderManager, self).__init__()

    @enable_log_and_session(resource='folder', event='create')
    def create(self, _logger, kwargs):
        folder_name = kwargs['folder_name']

        _logger.update_props(oplog_obj=folder_name)

        folder = self._create(**kwargs)
        return folder

    @inspect_func
    def _create(self, cluster_id=None, **kwargs):
        cmd = folder_api.FolderCreateCmd()
        repnum = kwargs.get('repnum') or 2
        if kwargs.get('ec_data') and kwargs.get('ec_code'):
            ec_data = kwargs['ec_data']
            ec_code = kwargs['ec_code']
            repnum = None
            if int(ec_data) < int(ec_code):
                raise exception.ParameterWrong("make sure ec_data big ec_code")
            
            host_num = len(_sw.db_hosts())
            ec_num = int(ec_code) + int(ec_data)
            if host_num < ec_num:
                raise Exception("节点个数不足,无法创建纠删码%s+%s副本的文件夹" % (ec_data, ec_code))

        else:
            ec_code = None
            ec_data = None

	cmd.ec_data = ec_data
	cmd.ec_code = ec_code
	cmd.repnum = repnum

        folder = _sw.get_folder(kwargs)
        folder_name = kwargs.get('folder_name')
        access_policy_id = kwargs.get('access_policy_id')
        username = kwargs.get('username')

        if folder:
            raise exception.AlreadyExists(name=kwargs.get('folder_name'))

        if not cluster_id:
            cluster_id = _sw.get_clusterid()

        values = {
            'status': 'creating',
            'name': folder_name,
            'cluster_id': cluster_id,
            'user_id': _sw.get_user_id(username),
            'repnum': repnum,
            'ec_data' : ec_data,
            'ec_code' : ec_code,
        }
        iprange = None
        if access_policy_id:
            values['access_policy_id'] = access_policy_id
            iprange = AccessPolicy.query.get(access_policy_id).iprange

        new_folder = Folder(values).save()

        cmd.target = str(folder_name)
        cmd.target_id = new_folder.id
        cmd.iprange = iprange

        self.taskm.async_post(cmd, callback=self.create_callback)

        return new_folder

    def create_callback(self, rsp):
        folder = Folder.query.filter_by(id=rsp.target_id).first()
        if rsp.success:
            folder.update({'status': 'normal'})
        else:
            folder.delete()
        return folder

    @enable_log_and_session(resource='folder', event='delete')
    def delete(self, _logger, kwargs):
        folder_id = kwargs['folder_id']
        folder = Folder.query.filter_by(id=folder_id).first()

        if not folder:
            raise exception.FolderNotFound(kwargs)

        _logger.update_props(oplog_obj=folder.name)

        kwargs['id'] = folder.id
        self._delete(folder, **kwargs)

        return True

    @inspect_func
    def _delete(self, folder, **kwargs):
        LOG.info('delete folder: %s: %s' % (folder.id, folder.name))

        name = folder.name
        folder.update({'status': 'deleting'})

        cmd = folder_api.FolderDeleteCmd()
        cmd.target = str(name)
        cmd.target_id = folder.id
        self.taskm.async_post(cmd, callback=self.delete_callback)

    def delete_callback(self, rsp):
        folder = Folder.query.filter_by(id=rsp.target_id).first()
        if rsp.success:
            folder.delete()
        else:
            folder.update({'status': 'normal'})
        return folder

    @enable_log_and_session(resource='folder', event='update')
    def update(self, _logger, kwargs):
        folder_id = kwargs['folder_id']
        folder = Folder.query.get(folder_id)
        if not folder:
            raise exception.FolderNotFound(kwargs)

        _logger.update_props(oplog_obj=folder.name)

        folder = self._update(folder, **kwargs)
        return folder

    @inspect_func
    def _update(self, folder, **kwargs):
        access_policy_id = kwargs.get('access_policy_id')

        values = {
            'status': 'updating',
        }
        iprange = None

        if access_policy_id:
            access_policy = AccessPolicy.query.get(access_policy_id)
            iprange = access_policy.iprange
            values.update({'access_policy_id': access_policy_id})
        else:
            values.update({'access_policy_id': None})

        updated_folder = folder.update(values)

        cmd = folder_api.FolderUpdateCmd()
        cmd.target = str(folder.name)
        cmd.target_id = folder.id
        cmd.iprange = iprange

        self.taskm.async_post(cmd, callback=self.update_callback)

        return updated_folder

    def update_callback(self, rsp):
        folder = Folder.query.get(rsp.target_id)
        if rsp.success:
            folder.update({'status': 'normal'})
        else:
            folder.delete()
        return folder


if __name__ == "__main__":
    vom = FolderManager()

